home *** CD-ROM | disk | FTP | other *** search
- /*
- ** descript.c
- **
- ** Practical Algorithms for Image Analysis
- **
- ** Copyright (c) 1997 ????
- */
-
- /*
- ** DESCRIPT
- **
- ** evaluation of Fourier descriptors for a plane curve
- ** encoded in a set {delta_phi(k), l(k)};
- **
- ** references:
- ** C. T. Zahn,
- ** Proc. Joint Intern. Conf. on Artif. Intelligence, May 1969, pp. 621 - 628;
- ** SLAC Report 70, Stanford Linear Accelerator Center, 1968;
- ** C. T. Zahn & R. Z. Roskies, IEEE Trans. Comp., Vol C-21, 269 - 281 (1972);
- **
- ** -->the truncated Fourier expansion derived by Z & R is computed
- ** in form of inner products using array processor functions
- **
- ** -->test shapes (see Z & R):
- ** four (xdrawfour.c), inverted L (fdzahnl.c)
- **
- ** ---------------------------------------------------------------------------
- **
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include "ip.h"
-
- #define EPS 0.00000001
- #define SQ2 1.414213562
-
- #define ON 1
- #define OFF 0
- #define FD_DEBUG ON
-
-
- /*
- * descriptors()
- * DESCRIPTION:
- * evaluate ZAHN-ROSKIES Fourier descriptors
- * ARGUMENTS:
- * dphik: delta phik for polygon (float *)
- * dlk: delta lk for polygon (float *)
- * mcp: length of dphik and dlk (long)
- * a_n: Fourier coefficients array (float *)
- * b_n: Fourier coefficients array (float *)
- * n_order: order of Fourier descriptors to compute (long)
- * RETURN VALUE:
- * none
- */
-
- void
- descriptors (float *dphik, float *dlk, long mcp, float *a_n, float *b_n, long n_order)
- {
- int k, n_ord;
- int fund_flag = OFF;
-
- float real_length, length;
- float dc_term, a, b, part_sum;
- float sne1k, snen, csn1k, csnn;
- float *angle;
- float *sne1, *sne, *csn1, *csn;
- float *mod, *arg;
-
-
- /*
- ** compute (in place) running sums of the elements in dlk
- ** and the corresponding phase angles required in the evaluation
- ** of the fundamental
- */
- angle = (float *)calloc((int)mcp, sizeof(float));
- sne1 = (float *)calloc((int)mcp, sizeof(float));
- csn1 = (float *)calloc((int)mcp, sizeof(float));
- sne = (float *)calloc((int)mcp, sizeof(float));
- csn = (float *)calloc((int)mcp, sizeof(float));
- if((angle == NULL) || (sne == NULL) || (csn1 == NULL) || (sne == NULL)
- || (csn == NULL))
- {
- printf("memory allocation error in function descriptors\n");
- exit(1);
- }
-
- /*
- ** evaluate contour length, based on curvature points
- */
- part_sum = *(dlk+0);
- for(k=1; k<mcp; k++)
- {
- part_sum += *(dlk+k);
- *(dlk+k) = part_sum; /* array of partial sums */
- }
- length = *(dlk+mcp-1);
-
- for(k=0; k<mcp; k++)
- *(angle+k) = (float)(2*PI*(*(dlk+k))/length);
-
- real_length = (float)(0.5*length);
- printf("\n...length = %f\n", real_length);
-
- /*
- ** dphik contains elements of delta_phik multiplied by PI/4;
- ** to speed up computation, factor out PI
- */
- for(k=0; k<mcp; k++)
- *(dphik+k) *= (float)0.25;
-
- #ifdef FD_DEBUG
- printf("...elements of dphik and dlk:\n");
- for(k=0; k<mcp; k++)
- printf("%7.4f %7.4f\n", *(dphik+k), *(dlk+k) );
- #endif
-
- /*
- * compute DC term
- */
- vdot(dphik, dlk, &dc_term, mcp);
- dc_term = (float)(-PI*(1.0 + dc_term/length));
- printf("...and we have a result for the DC term: %f \n", dc_term);
-
- /*
- ** execute routine to compute sine and
- ** cosine terms for fundamental, then fetch results
- */
- for(n_ord=0; n_ord<(int)n_order; n_ord++)
- {
-
- /*
- * compute coefficients for fundamental;
- */
- if(n_ord == 0)
- {
- for(k = 0; k < mcp; k++)
- *(angle + k) = *(angle + k) * (n_ord + 1);
- vsin(angle, sne1, mcp);
- vcos(angle, csn1, mcp);
- for (k=0; k<mcp; k++)
- {
- csn1k = *(csn1+k);
- sne1k = *(sne1+k);
- if( fabs(csn1k) < EPS ) csn1k = (float)0.0;
- if( fabs(sne1k) < EPS ) sne1k = (float)0.0;
-
- *(sne+k) = *(sne1+k) = sne1k;
- *(csn+k) = *(csn1+k) = csn1k;
- }
- fund_flag = ON;
- }
-
-
- /*
- ** employ double angle formulas to compute higher order coefficients
- */
- else
- {
- if( fund_flag != ON )
- {
- printf("\n");
- printf("hey, evaluate fundamental first!\n");
- printf(" something wrong!!\n");
- exit(1);
- }
- for (k=0; k<mcp; k++)
- {
- snen = *(sne+k);
- csnn = *(csn+k);
- *(sne+k) = snen*(*(csn1+k))+csnn*(*(sne1+k));
- *(csn+k) = csnn*(*(csn1+k))-snen*(*(sne1+k));
- }
- #ifdef FD_DEBUG
- printf("\n...n_ord = %d:\n", n_ord);
- for(k=0; k<10; k++)
- printf("......sne[%d] = %f csn[%d] = %f\n",
- k, *(sne+k), k, *(csn+k) );
- #endif
- }
-
-
- /*
- ** compute coefficients a_n, b_n
- */
-
- vdot(dphik, sne, &a, mcp);
- vdot(dphik, csn, &b, mcp);
-
- *(a_n+n_ord) = -a/(float)(n_ord+1);
- *(b_n+n_ord) = b/(float)(n_ord+1);
- }
-
- printf("...descriptors up to %ld-th order are:\n", n_order);
- for(n_ord=0; n_ord<(int)n_order; n_ord++)
- printf ("%7.3f %7.3f\n", *(a_n+n_ord), *(b_n+n_ord));
-
-
- mod = (float *)calloc((int)n_order, sizeof(float));
- arg = (float *)calloc((int)n_order, sizeof(float));
- /*
- ** calculate xy to polar coordinate transformation
- */
- vrtop(a_n, b_n, mod, arg, n_order);
- printf("...polar descriptors up to %ld-th order are:\n", n_order);
- for(n_ord=0; n_ord<(int)n_order; n_ord++)
- {
- if( *(arg+n_ord) < 0.0) *(arg+n_ord) += (float)(2.0*PI);
- printf("%7.3f %7.3f\n", *(mod+n_ord), *(arg+n_ord));
- }
-
- free(angle);
- free(sne1);
- free(csn1);
- free(sne);
- free(csn);
- }
-
- /*
- * vdot()
- * DESCRIPTION:
- * take the dot product of 2 vectors
- * and compute the sum
- * ARGUMENTS:
- * v1: first vector (float *)
- * v2: second vector (float *)
- * vsum: vector sum (float *)
- * vlen: length of vectors (long)
- * RETURN VALUE:
- * none
- */
-
- void
- vdot(float *v1, float *v2, float *vsum, long vlen)
- {
- float rsum = (float)0.0;
- int i;
-
- for(i = 0; i < vlen; i++)
- rsum = rsum + *(v1 + i) * (*(v2 + i));
- *vsum = rsum;
- }
-
- /*
- * vcos()
- * DESCRIPTION:
- * takes the cosine of a vector
- * ARGUMENTS:
- * source: input vector (float *) NOTE: radians!!
- * dest: output vector (float *)
- * vlen: vector length (long)
- * RETURN VALUE:
- * none
- */
-
- void
- vcos(float *source, float *dest, long vlen)
- {
- int i;
-
- for(i = 0; i < vlen; i++)
- *(dest + i) = (float)cos((double)*(source + i));
- }
-
- /*
- * vsin()
- * DESCRIPTION:
- * takes the sine of a vector
- * ARGUMENTS:
- * source: input vector (float *) NOTE: radians!!
- * dest: output vector (float *)
- * vlen: vector length (long)
- * RETURN VALUE:
- * none
- */
-
- void
- vsin(float *source, float *dest, long vlen)
- {
- int i;
-
- for(i = 0; i < vlen; i++)
- *(dest + i) = (float)sin((double)*(source + i));
- }
-
- /*
- * vrtop()
- * DESCRIPTION:
- * converts rectangular cartesian
- * coordinates to polar
- * ARGUMENTS:
- * x: input x vector (float *)
- * y: input y vector (float *)
- * mod: modulus output vector (float *)
- * arg: atan2 output vector (float *)
- * vlen: vector lengths (long)
- * RETURN VALUE:
- * none
- */
-
- void
- vrtop(float *x, float *y, float *mod, float *arg, long vlen)
- {
- int i;
-
- for(i = 0; i < vlen; i++) {
- *(mod + i) = (*(x + i))*(*(x + i)) + (*(y + i))*(*(y + i));
- *(arg + i) = (float)atan2(*(y + i), *(x + i));
- }
- }
-
- /*
- * msdescriptors()
- * DESCRIPTION:
- * wrapper for call to descriptors()
- * ARGUMENTS:
- * delta_phik: delta phik for polygon (float *)
- * delta_lk: delta lk for polygon (float *)
- * mcp: length of dphik and dlk (long)
- * a_n: Fourier coefficients array (float *)
- * b_n: Fourier coefficients array (float *)
- * n_order: order of Fourier descriptors to compute (long)
- * RETURN VALUE:
- * none
- */
-
- void
- msdescriptors(float *delta_phik, float *delta_lk, long mcp, float *a_n, float *b_n, long n_order)
- {
- int k;
-
- #ifdef FD_DEBUG
- printf("\nevaluation of Fourier descriptors (Zahn & Roskies)\n");
- printf("--------------------------------------------------\n");
-
- printf("...given: two vectors, delta_phik[] and delta_lk[]\n");
-
- printf(" delta_phik:\n");
- for(k=0; k<(int)mcp; k++)
- {
- printf( "%7.2f ",*(delta_phik+k) );
- if( (k+1)%8 == 0)
- printf ("\n");
- }
- printf ("\n delta_lk:\n");
- for (k=0; k<(int)mcp; k++)
- {
- printf( "%7.2f ",*(delta_lk+k) );
- if( (k+1)%8 == 0)
- printf ("\n");
- }
- #endif
-
- if(n_order > mcp)
- {
- printf("...polygon only has %ld vertices;");
- printf(" cannot yield %ld harmonics!\n", mcp, n_order);
- exit(1);
- }
- descriptors(delta_phik, delta_lk, mcp, a_n, b_n, n_order);
-
- }
-